﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ex2.IEnumerableExtensions
{
    public static class Extensions
    {
        public static dynamic Min<T>(this IEnumerable<T> collection) where T : IComparable<T>
        {
            if (collection == null)
            {
                throw new ArgumentNullException("Cannot apply Min<t> to null collection!");
            }

            if (collection.Count() == 0)
            {
                throw new ArgumentNullException("Cannot apply Min<t> to empty collection!");
            }

            dynamic minValue = default(T);
            foreach (T item in collection)
            {
                minValue = item;
                break;
            }
            foreach (var item in collection)
            {
                if (item.CompareTo(minValue) < 0)
                {
                    minValue = item;
                }
            }

            return minValue;
        }

        public static dynamic Max<T>(this IEnumerable<T> collection) where T : IComparable<T>
        {
            if (collection == null)
            {
                throw new ArgumentNullException("Cannot apply Min<t> to null collection!");
            }

            if (collection.Count() == 0)
            {
                throw new ArgumentNullException("Cannot apply Min<t> to empty collection!");
            }

            dynamic maxValue = default(T);
            foreach (T item in collection)
            {
                maxValue = item;
                break;
            }
            foreach (var item in collection)
            {
                if (item.CompareTo(maxValue) > 0)
                {
                    maxValue = item;
                }
            }

            return maxValue;
        }

        public static dynamic Average<T>(this IEnumerable<T> collection) where T : IComparable<T>
        {
            if (collection == null)
            {
                throw new ArgumentNullException("Cannot apply Min<t> to null collection!");
            }

            if (collection.Count() == 0)
            {
                throw new ArgumentNullException("Cannot apply Min<t> to empty collection!");
            }

            dynamic averageValue = default(T);

            averageValue = Sum<T>(collection) / collection.Count();

            return averageValue;
        }

        public static dynamic Sum<T>(this IEnumerable<T> collection) where T : IComparable<T>
        {
            if (collection == null)
            {
                throw new ArgumentNullException("Cannot apply Min<t> to null collection!");
            }

            if (collection.Count() == 0)
            {
                throw new ArgumentNullException("Cannot apply Min<t> to empty collection!");
            }

            dynamic sum = default(T);

            foreach (var item in collection)
            {
                sum += item;                
            }

            return sum;
        }

        public static dynamic Product<T>(this IEnumerable<T> collection) where T : IComparable<T>
        {
            if (collection == null)
            {
                throw new ArgumentNullException("Cannot apply Min<t> to null collection!");
            }

            if (collection.Count() == 0)
            {
                throw new ArgumentNullException("Cannot apply Min<t> to empty collection!");
            }

            dynamic product = 1;

            foreach (var item in collection)
            {
                product *= item;
            }

            return product;
        }
    }
    class IEnumerableExtensions
    {
        static void Main(string[] args)
        {
            IEnumerable<int> myCollection = new[] { 1, 2, 3, 4 };
            Console.WriteLine(myCollection.Min<int>());
            Console.WriteLine(myCollection.Max<int>());
            Console.WriteLine(myCollection.Sum<int>());
            Console.WriteLine(myCollection.Average<int>());
            Console.WriteLine(myCollection.Product<int>());
        }
    }
}
